import javafx.scene.control.TextField;

//@author A0096724W
public class AddSuggest {
	private final String DESCRIPTION = "\"description\"";
	private final String START_TIME = "from \\ start time \\";
	private final String END_TIME = "to \\ end time \\";
	
	private int descriptionStart = -1;
	private int descriptionEnd = -1;
	private int fromStart = -1;
	private int fromEnd = -1;
	private int toStart = -1;
	private int toEnd = -1;
	private int dueByStart = -1;
	private int dueByEnd = -1;
	private boolean isDoubleSpace = false;
	private int doubleSpacePos = -1;
	private boolean isSpace = false;

	AddSuggest(){

	}

	public void suggestNext(String current, int caretPos, TextField textField) {
		try {
		    resetVariables();
		    setEnvironment(current, caretPos - 1);
		    int initial = current.length();
		    if (isSpace) {
			if (current.equals("add ")) {
			    addDescription(current, textField, initial);
			}
		    } else if (isDoubleSpace) {
			if (isWithin(descriptionStart, descriptionEnd, caretPos)) {
			    if (isNoStartTime()) {
				addStartTime(current, textField, initial);
			    }
			} else if (isWithin(fromStart, fromEnd, caretPos)) {
			    if (isNoEndTime()) {
				addEndTime(current, textField, initial);
			    }
			} else if (isWithin(toStart, toEnd, caretPos)) {
			    addSpace(current, textField);
			} else if (isWithin(dueByStart, dueByEnd, caretPos)) {
			    addSpace(current, textField);
			}
		    }
		} catch (Exception e) {

		}
	}


	private void addSpace(String current, TextField textField) {
	    textField.replaceText(doubleSpacePos - 1, doubleSpacePos + 1, "");
	    textField.appendText(" ");
	    textField.end();
	}


	private void addEndTime(String current, TextField textField, int initial) {
	    textField.replaceText(doubleSpacePos - 1, doubleSpacePos + 1, "");
	    textField.appendText(" " + END_TIME);
	    textField.selectRange(initial + 3, initial + 13);
	}


	private void addStartTime(String current, TextField textField,
		int initial) {
	    textField.replaceText(doubleSpacePos - 1, doubleSpacePos + 1, "");
	    textField.appendText(" " + START_TIME);
	    textField.selectRange(initial + 5, initial + 17);
	}


	private void addDescription(String current, TextField textField,
		int initial) {
	    textField.setText(current + DESCRIPTION);
	    textField.selectRange(initial + 1, initial + 12);
	}


	//Initialise the variables required for autosuggest to suggest properly
	private void setEnvironment(String current, int caretPos) throws Exception{

	    char[] currentArray = current.toCharArray();

	    for (int i = 0; i < currentArray.length; i++) {    

		//Look for description
		initDescriptonRange(currentArray, i);

		//Look for from
		i = initStartOfFrom(currentArray, i);

		//Look for To
		i = initStartOfTo(currentArray, i);
		
		//Look for due by
		i = initStartOfDueBy(currentArray, i);

		//Look for backSlash
		initEndOfStartOrEndTIme(currentArray, i);

		//Look for SPACE
		initDoubleSpace(caretPos, currentArray, i); 
	    }
	}

	private void initDoubleSpace(int caretPos, char[] currentArray, int i) {
	    if (currentArray[i] == ' ') {
		if (i == (caretPos)) {
		    if (currentArray[i - 1] == ' ') {
			isDoubleSpace = true;
			doubleSpacePos = i;
		    } else {
			isSpace = true;
		    }
		}
	    }
	}

	private void initEndOfStartOrEndTIme(char[] currentArray, int i) {
	    if (currentArray[i] == '\\') {
		if (isOutsideDescription(i)) {
		    
		    if (fromStart > toStart) {
			if (fromStart > dueByStart) {
			    fromEnd = i;
			} else {
			    dueByEnd = i;
			}
		    }

		    if (toStart > fromStart) {
			if (toStart > dueByStart) {
			    toEnd = i;
			} else {
			    dueByEnd = i;
			}
		    }
		    
		    if (dueByStart > fromStart) {
			if (dueByStart > toStart) {
			    dueByEnd = i;
			} else {
			    toEnd = i;
			}
		    }
		}
	    }
	}

	private boolean isOutsideDescription(int i) {
	    return i < descriptionStart || i > descriptionEnd;
	}
	
	private int initStartOfDueBy(char[] currentArray, int i) {
	    if (currentArray[i] == 'd') {
	        if (isOutsideDescription(i)) {
	    	try {
	    	    String s1 = "";
	    	    String s2 = "";
	    	    
	    	    //Check next 7 or 8 characters
	    	    for (int j = 0; j < 8; j++) {
	    		if (j == 7) {
	    		    s1 += currentArray[i + j];
	    		} else {
	    		    s1 += currentArray[i + j];
	    		    s2 += currentArray[i + j];
	    		}
	    	    }
	    	    
	    	    //If is "due by" flag, save the indices
	    	    if (s1.equals("due by \\")) {
	    		if (fromStart > -1 && fromEnd > -1 && toStart > -1){
	    		    toEnd = i + 7;
	    		    i = i + 8;
	    		} else if (toStart > -1 && toEnd > -1 && fromStart > -1) {
	    		    fromEnd = i + 7;
	    		    i = i + 8;
	    		} else {
	    		    dueByStart = i + 7;
	    		    i = i + 8;
	    		}
	    	    }

	    	    if (s2.equals("due by\\")) {
	    		if (fromStart > -1 && fromEnd > -1 && toStart > -1){
	    		    toEnd = i + 6;
	    		    i = i + 7;
	    		} else if (toStart > -1 && toEnd > -1 && fromStart > -1) {
	    		    fromEnd = i + 6;
	    		    i = i + 7;
	    		} else {
	    		    dueByStart = i + 6;
	    		    i = i + 7;
	    		}
	    	    }
	    	} catch (Exception e) {

	    	}
	        }
	    }
	    return i;
	}

	private int initStartOfTo(char[] currentArray, int i) {
	    if (currentArray[i] == 't') {
	        if (isOutsideDescription(i)) {
	    	try {
	    	    String s1 = "";
	    	    String s2 = "";
	    	    
	    	    //Check next 3 or 4 characters
	    	    for (int j = 0; j < 4; j++) {
	    		if (j == 3) {
	    		    s1 += currentArray[i + j];
	    		} else {
	    		    s1 += currentArray[i + j];
	    		    s2 += currentArray[i + j];
	    		}
	    	    }
	    	    
	    	    //If is "to" flag, save the indices
	    	    if (s1.equals("to \\")) {
	    		if (fromStart > -1 && fromEnd > -1 && dueByStart > -1){
	    		    dueByEnd = i + 3;
	    		    i = i + 4;
	    		} else if (dueByStart > -1 && dueByEnd > -1 && fromStart > -1) {
	    		    fromEnd = i + 3;
	    		    i = i + 4;
	    		} else {
	    		    toStart = i + 3;
	    		    i = i + 4;
	    		}
	    	    }

	    	    if (s2.equals("to\\")) {
	    		if (fromStart > -1 && fromEnd > -1 && dueByStart > -1){
	    		    dueByEnd = i + 2;
	    		    i = i + 3;
	    		} else if (dueByStart > -1 && dueByEnd > -1 && fromStart > -1) {
	    		    fromEnd = i + 2;
	    		    i = i + 3;
	    		} else {
	    		    toStart = i + 2;
	    		    i = i + 3;
	    		}
	    	    }
	    	} catch (Exception e) {

	    	}
	        }
	    }
	    return i;
	}

	private int initStartOfFrom(char[] currentArray, int i) {
	    if (currentArray[i] == 'f') {
		if (isOutsideDescription(i)) {
		    try {

			//Check next 5 or 6 characters
			String s1 = "";
			String s2 = "";
			for (int j = 0; j < 6; j++) {
			    if (j == 5) {
				s1 += currentArray[i + j];
			    } else {
				s1 += currentArray[i + j];
				s2 += currentArray[i + j];
			    }

			}

			//If is "from" flag, save the indices
			if (s1.equals("from \\")) {
			    if (toStart > -1 && toEnd > -1 && dueByStart > -1){
				dueByEnd = i + 5;
				i = i + 6;
			    } else if (dueByStart > -1 && dueByEnd > -1 && toStart > -1) {
				toEnd = i + 5;
				i = i + 6;
			    } else {
				fromStart = i + 5;
				i = i + 6;
			    }
			}

			if (s2.equals("from\\")) {
			    if (toStart > -1 && toEnd > -1 && dueByStart > -1){
				dueByEnd = i + 4;
				i = i + 5;
			    } else if (dueByStart > -1 && dueByEnd > -1 && toStart > -1) {
				toEnd = i + 4;
				i = i + 5;
			    } else {
				fromStart = i + 4;
				i = i + 5;
			    }
			}
		    } catch (Exception e) {

		    }
		}
	    }
	    return i;
	}

	private void initDescriptonRange(char[] currentArray, int i)
		throws Exception {
	    if (currentArray[i] == '"') {
		if (descriptionStart != -1 && descriptionEnd != -1) {
		    throw new Exception("Too many double quotes");
		} else if (descriptionStart == -1) {
		    descriptionStart = i;
		} else {
		    descriptionEnd = i;
		}
	    }
	}

	private void resetVariables() {
		descriptionStart = -1;
		descriptionEnd = -1;
		fromStart = -1;
		fromEnd = -1;
		toStart = -1;
		toEnd = -1;
		dueByStart = -1;
		dueByEnd = -1;
		isDoubleSpace = false;
		doubleSpacePos = -1;
		isSpace = false;
	}
	
	private boolean isWithin(int start, int end, int pos) {
	    return (pos >= start && pos <= end);
	}
	
	private boolean isNoStartTime() {
	    return fromStart == -1 && fromEnd == -1;
	}
	
	private boolean isNoEndTime() {
	    return toStart == -1 && toEnd == -1;
	}

}
